package Demo_0408;

/**
 * @author:zhengyilong
 * @email:1797344574@qq.com
 * @phone:13479394730
 * @desc:
 * @DateTime:2022/4/8 11:06
 **/
public class ArrayListClass<E> {
    private int initcapacity = 10;//默认初始容量
    private E[] data;//声明一个数组
    private  int size;//实际长度
    private int capacity;//最大容量

    //创建一个初始容量为10的 list
    public ArrayListClass(){
        data = (E[])new Object[initcapacity];
        capacity = initcapacity;
        size = 0;
    }
    //创建一个指定容量的 list
    public ArrayListClass(int capacity){
        data = (E[])new Object[capacity];
        this.capacity = capacity;
        size = 0;
    }

    //长度等于容量时扩容
    private void updateCapacity(int newCapacity){
        //根据新容量创建新数组，将原来数组的值复制过来
        E[] newdata = (E[]) new Object[newCapacity];
        for (int i=0;i<size;i++){
            newdata[i]=data[i];
        }
        capacity = newCapacity;//更新容量
        data = newdata;//重新指向
    }

    public void CreateArrayList(E[] e){
        //将数组e的元素存在数组data里
        int j = 0;//数组data的下标
        for (int i = 0;i<e.length;i++){
            //考虑data数组装不下的问题，扩容
            if (size == capacity){//装满了
                updateCapacity(2*size);
            }
            data[j] = e[i];
            j++;
            //设置长度size
            size = j;
        }
    }

    //判断 list是否为空，为空，返回true 看size
    public boolean isEmpty(){
        if (size==0){
            return true;
        }
        return false;
    }

    //返回size属性
    public int size(){
        return size;
    }

    //将元素 e 添加到 list 的末尾
    public void add(E e){
        if (size == capacity){
            updateCapacity(capacity*2);
        }
        data[size]=e;
        size++;
    }

    //将元素 e 添加到下标为 i 的地方
    public void add(int i,E e){
        if (i <0 || i>size){
            throw new IllegalArgumentException("下标不在合法范围内");
        }
        for (int j = size;j>i;j--){
            data[j] = data[j-1];
        }
        data[i] = e;
        size++;
    }

    // 判断元素 e 是否存在当前集合，存在返回 true
    public boolean contains(Object o){
        for (E datum : data) {
            if (o==datum){
                return true;
            }
        }
        return false;
    }

    //返回下标为 i的元素
    public E get(int i){
        if (i <0 || i>size-1){
            throw new IllegalArgumentException("下标不在合法范围内");
        }
        return (E)data[i];
    }

    // 将下标 i 的元素 更改为 e
    public E set(int i,E e){
        if (i <0 || i>size-1){
            throw new IllegalArgumentException("下标不在合法范围内");
        }
        E datum = data[i];
        data[i]=e;
        return datum;
    }

    //返回集合中第一次出现 e 的下标，如果没有返回-1
    public int indexOf(Object o){
        int i = 0;//代表当前遍历到的下标
        while (i<size && !data[i].equals(o)){//循环数组，当有值等于e对的时候，结束循环
            i++;
        }
        if (i >= size){//没有这个值
            return -1;
        }
        return i;
    }

    //返回集合中最后一次出现 e 的下标，如果没有返回-1 倒序遍历
    public int lastIndexOf(Object o){
        int i = size-1;//代表当前遍历到的下标
        while (i>=0 && !data[i].equals(o)){//循环数组，当有值等于e对的时候，结束循环
            i--;
        }
        if (i < 0){//没有这个值
            return -1;
        }
        return i;
    }

    // 清空 list 的元素
    public void clear(){
        data = (E[])new Object[initcapacity];
        capacity = initcapacity;
        size = 0;
    }

    //从list 中移除下标为 i 的元素，并返回这个元素
    public E remove(int i){
        //判断i是否合理
        if (i <0 || i>size-1){
            throw new IllegalArgumentException("下标不在合法范围内");
        }

        E datum = data[i];

        for (int j = i;j<size-1;j++){
            data[j] = data[j+1];//前移了一位
        }
        size--;
        //减容问题 当size = capacity/4 兼容减一半 capacity/2
        if (size == capacity/4 && capacity > initcapacity){
            updateCapacity(capacity/2);
        }
        return datum;
    }

    //移除list中第一个值为 o 的元素
    public boolean remove(Object o){
        //调用自定义方法，找到第一个值为o的下标，如果没找到，返回false
        int i = indexOf(o);
        if (i==-1){
            return false;
        }
        //调用自定义方法，删除下标为i的元素
        E remove = remove(i);
        return true;
    }

    //将线性表的所有元素拼接成字符串并返回
    public String toString(){
        //遍历数组，元素拼接字符串
        String answer = "";
        for (int i = 0;i<size;i++){
            answer += data[i]+" ";
        }
        return answer;
    }
}

